package com.thiswhyme.gateway.sentinel.service.biz;

import com.alibaba.csp.sentinel.slots.block.RuleConstant;
import com.alibaba.fastjson.JSONObject;
import com.alibaba.fastjson.serializer.SerializerFeature;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.cloud.client.ServiceInstance;
import org.springframework.cloud.client.discovery.DiscoveryClient;
import org.springframework.cloud.gateway.route.RouteDefinition;
import org.springframework.stereotype.Service;
import org.springframework.util.CollectionUtils;

import java.util.List;
import java.util.stream.Collectors;

/**
 * @description: 熔断规则更新处理器抽象类
 * @author: thiswhyme
 * @date: 2021/4/28
 */
@Slf4j
@Service
public class DegradeRuleUpdateHandler extends AbstractRuleUpdateHandler {

    @Autowired
    private DiscoveryClient discoveryClient;

    @Override
    public String getRuleDatasourceKey() {
        //TODO 此处可读配置
        return "ds3";
    }

    @Override
    public String genNewRule(List<RouteDefinition> routes, String currentRuleContent) {
        List<IpDegradeRule> currentRules = JSONObject.parseArray(currentRuleContent, IpDegradeRule.class);
        for(RouteDefinition route: routes) {
            String uri = route.getUri().toString();
            if(!uri.startsWith("lb://")) {
                continue;
            }
            String serviceName = uri.replace("lb://", "");

            List<ServiceInstance> instances = discoveryClient.getInstances(serviceName);
            if(CollectionUtils.isEmpty(instances)) {
                continue;
            }

            if(!CollectionUtils.isEmpty(currentRules)) {
                currentRules.removeIf(rule -> serviceName.equals(rule.getIpFrom()));
            }

            List<String> urls = instances.stream().map(instance -> instance.getHost() + ":" + instance.getPort()).collect(Collectors.toList());
            for (String url : urls) {
                //TODO 此处可改造为通过配置读取
                IpDegradeRule newRule = new IpDegradeRule();
                newRule.setIpFrom(serviceName);
                newRule.setResource(url);
                newRule.setCount(1000);
                newRule.setTimeWindow(5);
                newRule.setGrade(RuleConstant.DEGRADE_GRADE_RT);
                newRule.setRtSlowRequestAmount(RuleConstant.DEGRADE_DEFAULT_SLOW_REQUEST_AMOUNT);
                newRule.setMinRequestAmount(RuleConstant.DEGRADE_DEFAULT_MIN_REQUEST_AMOUNT);
                newRule.setLimitApp(null);

                currentRules.add(newRule);
            }
        }

        //更新最新降级配置到nacos
        return JSONObject.toJSONString(currentRules, SerializerFeature.PrettyFormat);
    }
}
